#include <cstring>
#include <exception>
#include <iostream>
#include <memory>
#include <openssl/evp.h>
using namespace std;

auto ctxdeleter = [](EVP_CIPHER_CTX* p) {
	if (p != nullptr) {
		EVP_CIPHER_CTX_free(p);
	}
};

int main()
{
	try {
		unique_ptr<const unsigned char[]> pdata(new const unsigned char[] { "123456" });
		unique_ptr<unsigned char[]> pout(new unsigned char[1024] { 0 });
		unique_ptr<unsigned char[]> pout2(new unsigned char[1024] { 0 });
		size_t datalen = strlen(reinterpret_cast<const char*>(pdata.get())) + 1;
		unique_ptr<const unsigned char[]> pkey(new const unsigned char[32] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
		unique_ptr<const unsigned char[]> piv(new const unsigned char[16] { 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
		unique_ptr<EVP_CIPHER_CTX, decltype(ctxdeleter)> pctx(EVP_CIPHER_CTX_new(), ctxdeleter);
		auto aescipher = EVP_aes_256_cbc();
		int outlen = 0;
		int outlen2 = 0;
		EVP_CipherInit(pctx.get(), aescipher, pkey.get(), piv.get(), 1);
		EVP_CipherUpdate(pctx.get(), pout.get(), &outlen, pdata.get(), 7);
		EVP_CipherFinal(pctx.get(), pout.get() + outlen, &outlen2);
		cout<<pout.get()<<endl;
		size_t outlenin = outlen + outlen2;
		EVP_CipherInit(pctx.get(),aescipher, pkey.get(), piv.get(), 0);
		EVP_CipherUpdate(pctx.get(), pout2.get(), &outlen, pout.get(), outlenin);
		EVP_CipherFinal(pctx.get(), pout2.get() + outlen, &outlen2);
		cout<<pout2.get()<<endl;
	} catch (...) {
		cerr << "error" << endl;
	}
}
